#include "imgui/model/Editor.h"

using namespace ImGui::Model;

ImGui::Model::Editor::Editor()
{
}

void Editor::ShowScene(const Ogl::Model::Scene *scene)
{

    Show("name", scene->m_Name);

    TreeNode(scene->m_RootNode.get());

    this->ShowFramebuffer(scene->m_MeshesRenderTarget->m_OutColors[0].get(), ImVec2(200, 150));

    if (ImGui::TreeNode("Meshes"))
    {
        for (const auto& mesh : scene->m_Meshes)
        {
            ShowMesh(mesh.get());
        }
        ImGui::TreePop();
    }

    for (const auto &mat : scene->m_Materials)
    {
        ShowMaterial(mat.get());
    }

    for (const auto &anim : scene->m_Animations)
    {
        ShowAnimation(anim.get());
    }
    for(const auto& camera:scene->m_Cameras)
    {
        ShowCamera(camera.get());
    }
    for(const auto& light:scene->m_Lights)
    {
        ShowLight(light.get());
    }
}

void ImGui::Model::Editor::PassScene(const Ogl::Model::Scene *scene)
{
    // deleted 
}

void ImGui::Model::Editor::TreeNode(const Ogl::Model::Node *node)
{
    if (ImGui::TreeNode(node->m_Name.c_str()))
    {
        for (const auto &child : node->m_Childern)
        {
            TreeNode(child.get());
        }

        ImGui::TreePop();
    }
}

void ImGui::Model::Editor::ShowMesh(const Ogl::Model::Mesh *mesh)
{

    Show("name", mesh->m_Name);
    this->ShowFramebuffer(mesh->m_MeshRT->m_OutColors[0].get(), ImVec2(200, 150));
    if (mesh->HasBones())
    {
        this->ShowFramebuffer(mesh->m_SkinnedMeshRT->m_OutColors[0].get(), ImVec2(200, 150));

    }
}

void ImGui::Model::Editor::ShowAnimation(const Ogl::Model::Animation *anim)
{

    Show("name ", anim->m_Name);
    Show("Duration", anim->m_Duration);
    Show("TicksPerSecond", anim->m_TicksPerSecond);

    for (const auto &it: anim->m_Channels)
    {
        const auto channel = it.second;
        
        ShowChannel(channel.get());
    }
}

void ImGui::Model::Editor::ShowChannel(const Ogl::Model::Channel *channel)
{
    Show("nodeName", channel->m_NodeName);
}

void ImGui::Model::Editor::ShowCamera(const Ogl::Model::Camera *camera)
{
    Show("name", camera->m_Name);
}

void ImGui::Model::Editor::ShowLight(const Ogl::Model::Light *light)
{
    ImGui::Text("%s", light->m_Name.c_str());
    Show("Position", light->m_Position);
    Show("Direction", light->m_Direction);
    Show("Up", light->m_Up);
    Show("AttenuationConstant", light->m_AttenuationConstant);
    Show("AttenuationLinear", light->m_AttenuationLinear);
    Show("AttenuationQuadratic", light->m_AttenuationQuadratic);
    Show("ColorDiffuse", light->m_ColorDiffuse);
    Show("ColorSpecular", light->m_ColorSpecular);
    Show("ColorAmbient", light->m_ColorAmbient);
    Show("AngleInnerCone", light->m_AngleInnerCone);
    Show("AngleOuterCone", light->m_AngleOuterCone);
    Show("Size", light->m_Size);
}

void ImGui::Model::Editor::ShowMaterial(const Ogl::Model::Material *mat)
{
    Show("name", mat->m_Name);

    ShowTextures(mat, "NONE");
    ShowTextures(mat, "DIFFUSE");
    ShowTextures(mat, "SPECULAR");
    ShowTextures(mat, "AMBIENT");
    ShowTextures(mat, "EMISSIVE");
    ShowTextures(mat, "HEIGHT");
    ShowTextures(mat, "NORMALS");
    ShowTextures(mat, "SHININESS");
    ShowTextures(mat, "OPACITY");
    ShowTextures(mat, "DISPLACEMENT");
    ShowTextures(mat, "LIGHTMAP");
    ShowTextures(mat, "REFLECTION");
    ShowTextures(mat, "BASE_COLOR");
    ShowTextures(mat, "NORMAL_CAMERA");
    ShowTextures(mat, "EMISSION_COLOR");
    ShowTextures(mat, "METALNESS");
    ShowTextures(mat, "DIFFUSE_ROUGHNESS");
    ShowTextures(mat, "AMBIENT_OCCLUSION");
    ShowTextures(mat, "UNKNOWN");
}

void ImGui::Model::Editor::ShowTextures(const Ogl::Model::Material *mat, const std::string &info)
{
    const auto it = mat->m_Textures.find(info);

    ImGui::Text("%s", info.c_str());
    if (it != mat->m_Textures.end())
    {
        const auto &textures = it->second;
        for (const auto &tex : textures)
        {
            ShowTexture(tex.get());
        }
        ImGui::Separator();
    }
}

void ImGui::Model::Editor::ShowTexture(const Ogl::Gut::Texture2D *tex, ImVec2 sz)
{
    ImGui::Image((ImTextureID)tex->m_Id, sz);
    ImGui::SameLine();
}

void ImGui::Model::Editor::ShowAABB(const Ogl::Model::AABB &aabb)
{
    Show("min", aabb.m_Min);
    Show("max", aabb.m_Max);
}

void ImGui::Model::Editor::Show(const std::string &label, const float &v)
{
    ImGui::Text("%s (%f)", label.c_str(), v);
}

void ImGui::Model::Editor::Show(const std::string &label, const glm::vec2 &v)
{
    ImGui::Text("%s (%f,%f)", label.c_str(), v.x, v.y);
}

void ImGui::Model::Editor::Show(const std::string &label, const glm::vec3 &v)
{
    ImGui::Text("%s (%f,%f,%f)", label.c_str(), v.x, v.y, v.z);
}

void ImGui::Model::Editor::Show(const std::string &label, const glm::vec4 &v)
{
    ImGui::Text("%s (%f,%f,%f,%f)", label.c_str(), v.x, v.y, v.z, v.w);
}

void ImGui::Model::Editor::Show(const std::string &label, const std::string &name)
{
    ImGui::Text("%s %s", label.c_str(), name.c_str());
}


void ImGui::Model::Editor::ShowFramebuffer(const Ogl::Gut::Texture2D *tex, ImVec2 sz, ImVec2 uv0, ImVec2 uv1)
{
    ImGui::Image((ImTextureID)tex->m_Id, sz, uv0, uv1);
}
